package com.zyl.blog.tasks.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.zyl.blog.common.domain.task.bean.TaskAlert;
import com.zyl.blog.common.domain.task.bean.TaskLogInfo;
import com.zyl.blog.common.utils.Extreme.LogUtil;
import com.zyl.blog.tasks.enums.AlertLevel;
import com.zyl.blog.tasks.enums.TaskStatusEnum;
import com.zyl.blog.tasks.mapper.TaskAlertMapper;
import com.zyl.blog.tasks.service.TaskAlertService;
import com.zyl.blog.tasks.utils.AsyncUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @version v1.0
 * @ProjectName: Personal_Blog_Server
 * @Package: com.zyl.blog.tasks.service.impl
 * @ClassName: ITaskAlertService
 * @Description: 任务警告信息业务实现类
 * @Author FinalFantasy
 * @Date 2025/8/12-16:01
 */
@Service
@RequiredArgsConstructor
public class ITaskAlertService extends MPJBaseServiceImpl<TaskAlertMapper, TaskAlert>
    implements TaskAlertService {

    private final TaskAlertMapper taskAlertMapper;

    private final AsyncUtil asyncUtil;
    // 可选：注入邮件/短信等通知服务
    //private final EmailNotificationService emailNotificationService;

    /**
     * 发送任务告警（异步执行，避免阻塞主流程）
     */
    @Override
    public void sendTaskAlert(TaskLogInfo logInfo) {
        // 异步执行告警逻辑，不阻塞任务日志记录
        asyncUtil.execute(() -> doSendAlert(logInfo));
    }

    /**
     * 实际执行告警发送的核心逻辑
     */
    private void doSendAlert(TaskLogInfo logInfo) {
        try {
            /* 校验告警必要性（避免重复发送） */
            if (!isAlertNeeded(logInfo)) {
                LogUtil.info("任务[{}]告警无需发送，已存在未解决的相同告警", logInfo.getTaskName());
                return;
            }

            /* 构建告警实体 */
            TaskAlert alert = buildTaskAlert(logInfo);

            /* 持久化告警记录 */
            /* MyBatisPlus的save方法会自动填充ID，所以无需调用insert方法 */
            taskAlertMapper.insert(alert);
            LogUtil.info("任务告警已记录，告警ID: {}, 任务名称: {}", alert.getId(), logInfo.getTaskName());

            /* 发送通知（可扩展多种方式） */
            //sendNotification(alert);

        } catch (Exception e) {
            LogUtil.error("发送任务告警失败，任务名称: {}", null, logInfo.getTaskName(), e);
        }
    }

    /**
     * 判断是否需要发送告警（去重逻辑）
     * 规则：近10分钟内不存在相同任务的未解决告警
     */
    private boolean isAlertNeeded(TaskLogInfo logEntity) {
        LocalDateTime tenMinutesAgo = LocalDateTime.now().minusMinutes(10);
        List<TaskAlert> recentAlerts = taskAlertMapper.selectList(
                new LambdaQueryWrapper<TaskAlert>()
                        .eq(TaskAlert::getTaskName, logEntity.getTaskName())
                        .eq(TaskAlert::getUsername, logEntity.getOperator())
                        .eq(TaskAlert::getIsResolved, 0)
                        .ge(TaskAlert::getAlertTime, tenMinutesAgo)
        );
        return recentAlerts.isEmpty();
    }

    /**
     * 构建任务告警实体
     */
    private TaskAlert buildTaskAlert(TaskLogInfo logInfo) {
        TaskAlert alert = new TaskAlert();
        alert.setTaskName(logInfo.getTaskName());
        alert.setUsername(logInfo.getOperator());
        alert.setAlertTime(LocalDateTime.now());
        alert.setAlertLevel(resolveAlertLevel(logInfo.getStatus()).name());
        alert.setAlertMessage(buildAlertMessage(logInfo));
        alert.setStackTrace(StringUtils.abbreviate(logInfo.getErrorStack(), 3000)); // 限制堆栈长度
        alert.setIsResolved(0);
        return alert;
    }

    /**
     * 根据任务状态解析告警级别
     */
    private AlertLevel resolveAlertLevel(int status) {
        // 超时和失败属于严重错误，其他属于警告
        if (status == TaskStatusEnum.TIMEOUT.getCode() || status == TaskStatusEnum.FAILED.getCode()) {
            return AlertLevel.ERROR;
        }
        return AlertLevel.WARN;
    }

    /**
     * 构建告警消息内容
     */
    private String buildAlertMessage(TaskLogInfo logInfo) {
        TaskStatusEnum status = TaskStatusEnum.values()[logInfo.getStatus()];
        return String.format(
                "任务执行异常 - 任务名称: %s, 状态: %s, 耗时: %dms, 错误代码: %s",
                logInfo.getTaskName(),
                status.getDesc(),
                logInfo.getExecuteDuration(),
                logInfo.getErrorCode()
        );
    }

    /**
     * 构建邮件通知内容
     */
    private String buildEmailContent(TaskAlert alert) {
        return """
                <h3>任务告警通知</h3>
                <p>告警时间: %s</p>
                <p>告警级别: %s</p>
                <p>任务名称: %s</p>
                <p>所属用户: %s</p>
                <p>告警信息: %s</p>
                <p>错误摘要: %s</p>
                <p>请及时登录系统查看详情并处理。</p>
                """.formatted(
                alert.getAlertTime(),
                alert.getAlertLevel(),
                alert.getTaskName(),
                alert.getUsername(),
                alert.getAlertMessage(),
                StringUtils.abbreviate(alert.getStackTrace(), 500)
        );
    }
}
